package com.liusand.user.service.Impl;

import com.liusand.common.constans.RedisPrefixCode;
import com.liusand.common.utils.Utils;
import com.liusand.entity.dto.LocationDto;
import com.liusand.entity.pojo.User;
import com.liusand.entity.vo.PageInfo;
import com.liusand.entity.vo.UserVo;
import com.liusand.user.mapper.UserMapper;
import com.liusand.user.service.LocationService;
import com.liusand.user.thread.UserThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author :liusha
 * packageName :com.liusand.user.service.Impl
 * fileName :LocationServiceImpl
 * creationTime :2022/12/15 20:43
 */
@Service
@Slf4j
public class LocationServiceImpl implements LocationService {
    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public boolean sendLocationInfo(LocationDto locationDto) {
        if(locationDto.getLongitude() == null || locationDto.getLatitude() == null){
            return false;
        }
        Point point = new Point(locationDto.getLongitude(), locationDto.getLatitude());
        Long add = redisTemplate.opsForGeo().add(RedisPrefixCode.LOCATION_USER_KEY, point, UserThreadLocalUtil.getId());
        log.info("Redis add result:{}", add);
        return true;
    }

    @Override

    public PageInfo<UserVo> getNearPeople(Integer gender, Integer radius, Integer page, Integer pageSize) {
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                // 包含距离
                .includeDistance()
                // 包含经纬度
                .includeCoordinates()
                // 升序
                .sortAscending();
                // 最大查询数量
//                .limit(10);
        String id = UserThreadLocalUtil.getId();
        GeoResults<RedisGeoCommands.GeoLocation<String>> content = redisTemplate.opsForGeo().radius(RedisPrefixCode.LOCATION_USER_KEY, id, new Distance(radius, Metrics.KILOMETERS), args);
        PageInfo<UserVo> pageInfo = new PageInfo<>();
        if(content == null){
            pageInfo.setTotal(0L);
            pageInfo.setCurrent(1);
            pageInfo.setPageSize(pageSize);
            return pageInfo;
        }
        List<String> ids = new ArrayList<>();
        Integer start = (page - 1) * pageSize;
//        for(int i = start; i < content.getContent().size() && i < start + pageSize; i++){
//            List<GeoResult<RedisGeoCommands.GeoLocation<String>>> list = content.getContent();
//            ids.add(list.get(i).getContent().getName());
//        }
        for(int i = 0; i < content.getContent().size(); i++){
            List<GeoResult<RedisGeoCommands.GeoLocation<String>>> list = content.getContent();
            ids.add(list.get(i).getContent().getName());
        }
        List<UserVo> userVos = new ArrayList<>();
        if(ids.size() != 0){
            userVos = userMapper.selectUserVoByIds(ids);
            if(userVos != null){
                Stream<UserVo> userVoStream = userVos.stream();
                if(gender != null){
                    userVoStream = userVoStream.filter(
                            vo -> vo.getGender().equals(gender)
                    );
                }
                userVoStream = userVoStream.skip(start).limit(pageSize);
                userVos = userVoStream.collect(Collectors.toList());


                User user = userMapper.selectUserById(id);
                int userAge = Utils.birthday2age(user.getBirthday());
                for(UserVo userVo : userVos){
                    int age = Utils.birthday2age(userVo.getBirthday());
                    log.info("{}", age);
                    userVo.setAge(age);
                    userVo.setScore(Utils.getScore(userAge, age));
                }
            }
        }


        pageInfo.setInfo(userVos);
        pageInfo.setPageSize(pageSize);
        pageInfo.setCurrent(page);
        pageInfo.setTotal((long)content.getContent().size());

        return pageInfo;
    }
}
